﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Zyg.SSO.Core.Business
{
    public enum RelationType
    {
        OneToMany,
        ManyToMany
    }

    /// <summary>
    /// Collection base
    /// </summary>
    public abstract class BusinessCollectionBase<TYPE, KEY> where TYPE : BusinessBase<TYPE, KEY>, new()
    {
        #region Fields and Properties

        private bool isChanged = false;
        /// <summary>
        /// Gets if this collection's data has been changed.
        /// </summary>
        public virtual bool IsChanged
        {
            get { return isChanged; }
            protected set { isChanged = value; }
        }

        private RelationType relationType = RelationType.OneToMany;
        /// <summary>
        /// Get or Set the relation type between entities.
        /// </summary>
        protected RelationType RelationType
        {
            get { return relationType; }
            set { relationType = value; }
        }

        #endregion

        #region Data

        private IList<TYPE> elements;

        protected IList<TYPE> Elements
        {
            get
            {
                if (elements == null)
                    Load();
                return elements;
            }
            set
            {
                IsChanged = true;
                elements = value;
            }
        }

        /// <summary>
        /// Get count of collection
        /// </summary>
        public int Count
        {
            get
            {
                if (elements == null)
                    Load();
                return elements.Count;
            }
        }

        public TYPE this[int index]
        {
            get
            {
                if (elements == null)
                    Load();
                return elements[index];
            }
            protected set
            {
                if (value != elements[index])
                {
                    elements[index] = value;
                    IsChanged = true;
                }
            }
        }

        #endregion

        #region Methods

        /// <summary>
        /// Marks the collection as being an clean, which means not dirty.
        /// </summary>
        protected void MarkOld()
        {
            IsChanged = false;
        }

        protected abstract void Load();

        protected abstract void Update();

        public void Save()
        {
            if (IsChanged)
            {
                Update();
            }
        }

        public virtual void AddOnSave(TYPE element)
        {
            if (elements == null)
                Load();

            elements.Add(element);

            IsChanged = true;
            OnCollectionChanged();
        }

        public virtual void DeleteOnSave(TYPE element)
        {
            if (elements == null)
                Load();

            #region Method 1
            /*
            if (this.RelationType == RelationType.ManyToMany)
            {
                elements.Remove(element);
                IsChanged = true;
                OnCollectionChanged();
            }
            else // if(RelationType == RelationType.OneToMany)
            {
                for (int i = Elements.Count - 1; i > -1; i--)
                {
                    if (Elements[i] == element)
                    {
                        Elements[i].DeleteOnSave();

                        IsChanged = true;

                        OnCollectionChanged();
                    }
                }
            }
            */
            #endregion Method 1

            #region Method 2

            for (int i = Elements.Count - 1; i > -1; i--)
            {
                if (Elements[i] == element)
                {
                    Elements[i].DeleteOnSave();

                    IsChanged = true;

                    OnCollectionChanged();
                }
            }

            #endregion Method 2
        }

        public virtual void DeleteAtOnSave(int index)
        {
            if (elements == null)
                Load();

            #region Method 1
            /*
            if (this.RelationType == RelationType.ManyToMany)
            {
                elements.RemoveAt(index);
                IsChanged = true;
                OnCollectionChanged();
            }
            else// if (RelationType == RelationType.OneToMany)
            {
                if (index > -1 && index < Elements.Count)
                {
                    Elements[index].DeleteOnSave();
                    IsChanged = true;
                    OnCollectionChanged();
                }
            }
            */
            #endregion Method 1

            #region Method 2

            if (index > -1 && index < Elements.Count)
            {
                Elements[index].DeleteOnSave();
                IsChanged = true;
                OnCollectionChanged();
            }

            #endregion
        }

        public virtual void ClearOnSave()
        {
            if (elements == null)
                Load();

            for (int i = Elements.Count - 1; i > -1; i--)
            {
                Elements[i].DeleteOnSave();
            }
        }

        #endregion

        #region Events

        public event EventHandler CollectionChanged;
        /// <summary>
        /// Collection changed.
        /// </summary>
        public virtual void OnCollectionChanged()
        {
            if (CollectionChanged != null)
            {
                CollectionChanged(this, new EventArgs());
            }
        }

        #endregion
    }
}
